package com.zhijiang.hospital.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhijiang.hospital.entity.InpatientOperationData;
import com.zhijiang.hospital.entity.dto.InpatientOperationDataDto;
import com.zhijiang.hospital.mapper.InpatientOperationDataMapper;
import com.zhijiang.hospital.service.InpatientOperationDataService;
import com.zhijiang.util.BaseQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 75936
 * @version 1.0
 * @project zhijiang_hospital-data
 * @description
 * @date 2022-10-25 10:41:09
 */
@Service
@Slf4j
public class InpatientOperationDataServiceImpl extends ServiceImpl<InpatientOperationDataMapper, InpatientOperationData> implements InpatientOperationDataService {
    @Autowired
    private InpatientOperationDataMapper inpatientOperationDataMapper;

    @Override
    public List<InpatientOperationDataDto> loadAll() {
        List<InpatientOperationDataDto> list = inpatientOperationDataMapper.loadAll();
        log.error("service数据有误", list);

        return list;
    }

    @Override
    public InpatientOperationData loadOne(String id) {
        return inpatientOperationDataMapper.selectById(id);
    }

    @Override
    public void addOne(InpatientOperationData inpatientOperationData) {

        //inpatientOperationData
        inpatientOperationDataMapper.insert(inpatientOperationData);
    }

    @Override
    public Page<InpatientOperationData> loadPageList(BaseQuery baseQuery) {
        QueryWrapper<InpatientOperationData> inpatientOperationDataQueryWrapper = new QueryWrapper<>();
        inpatientOperationDataQueryWrapper.
                apply(StrUtil.isNotBlank(baseQuery.getStartTime()),
                        "create_time >= to_date('" + baseQuery.getStartTime() + "','yyyy-mm-dd hh24:mi:ss')").
                apply(StrUtil.isNotBlank(baseQuery.getEndTime()),
                        "create_time <= to_date('" + baseQuery.getEndTime() + "','yyyy-mm-dd hh24:mi:ss')")
                .eq(StringUtils.isNotBlank(baseQuery.getDepartment()) && !baseQuery.getDepartment().equals("全部科室"), "dept_Name", baseQuery.getDepartment());
        return inpatientOperationDataMapper.selectPage(new Page<>(baseQuery.getPage(), baseQuery.getPageSize()), inpatientOperationDataQueryWrapper);
    }

    @Override
    public String writeExcel(HttpServletResponse response) throws IOException {
        List<InpatientOperationData> inpatientOperationData = inpatientOperationDataMapper.selectList(null);
        // 告诉浏览器用什么软件可以打开此文件
        response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 下载文件的默认名称
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("员工信息表.xlsx", "utf-8"));
        //4. 创建输入、输出流
        EasyExcel.write(response.getOutputStream(), InpatientOperationData.class).sheet("住院运行数据").doWrite(inpatientOperationData);
        return "写出成功";
    }

    @Override
    @Transactional
    public void readExcel(MultipartFile file) throws IOException {

        EasyExcel.read(file.getInputStream(), InpatientOperationData.class, new AnalysisEventListener<InpatientOperationData>() {
            /**
             * 批处理阈值，作用：减轻数据库的压力
             */
            private static final int BATCH_COUNT = 2;

            /**
             * 存储员工对象
             */
            List<InpatientOperationData> list = new ArrayList<InpatientOperationData>(BATCH_COUNT);

            //easyExcel每次从Excel中读取一行数据就会调用一次invoke方法
            @Override
            public void invoke(InpatientOperationData inpatientOperationData, AnalysisContext analysisContext) {

                list.add(inpatientOperationData);

                if (list.size() >= BATCH_COUNT) {

                    list.clear();
                }
            }

            //easyExcel在将Excel表中数据读取完毕后，最终执行此方法
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                list.stream().forEach(s -> log.info(String.valueOf(s)));
                //最后,如果size<BATCH_COUNT就在这里进行数据的处理
                if (list.size() > 0) {

                }
            }
            // 在此匿名内部类的方法里，throw new ExcelAnalysisStopException()就会终止easyExcel的运行。

            /**
             *监听器实现这个方法就可以在读取数据的时候获取到异常信息
             * @param exception
             * @param context
             * @throws Exception
             */
            @Override
            public void onException(Exception exception, AnalysisContext context) {
                // 此方法能接住，在此匿名内部类的方法里抛出的异常，并进行处理，然后继续invoke方法。
                log.error("解析失败的原因:" + exception.getMessage());
                if (exception instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
                    log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                            excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
                }
            }
        }).sheet().headRowNumber(1).doRead();
    }

    @Override
    public List<String> loadDept() {
        List<String> list = inpatientOperationDataMapper.selectList(null).stream().map(InpatientOperationData::getDeptName).distinct().collect(Collectors.toList());
        return list;
    }


    @Override
    public List<String> loadPatientNumberByDay(BaseQuery baseQuery) {
        LambdaQueryWrapper<InpatientOperationData> eq = new QueryWrapper<InpatientOperationData>().lambda().
                apply(StrUtil.isNotBlank(baseQuery.getStartTime()),
                        "create_time >= to_date('" + baseQuery.getStartTime() + "','yyyy-mm-dd hh24:mi:ss')").
                apply(StrUtil.isNotBlank(baseQuery.getEndTime()),
                        "create_time <= to_date('" + baseQuery.getEndTime() + "','yyyy-mm-dd hh24:mi:ss')");
        return inpatientOperationDataMapper.selectList(eq).
                stream().map(InpatientOperationData::getPatientNumber).
                collect(Collectors.toList());
    }

    @Override
    public List<String> loadPatientNumberOfDay() {
        List<String> list = inpatientOperationDataMapper.loadPatientNumberOfDay().
                stream().map(InpatientOperationData::getPatientNumber).
                collect(Collectors.toList());
        return list;
    }

    @Override
    public List<String> loadPatientNumberOfMonth() {
        List<String> list = inpatientOperationDataMapper.loadPatientNumberOfMonth().
                stream().map(InpatientOperationData::getPatientNumber).
                collect(Collectors.toList());
        return list;
    }

    @Override
    public List<String> loadPatientNumberOfYear() {
        List<String> list = inpatientOperationDataMapper.loadPatientNumberOfYear().stream().map(InpatientOperationData::getPatientNumber).collect(Collectors.toList());
        return list;
    }


    @Override
    public Page<List<InpatientOperationData>> findinpatientOperationData(BaseQuery baseQuery) {
        QueryWrapper<List> wapper = new QueryWrapper<>();
        //inpatientOperationDataMapper.selectPage(new Page<List<InpatientOperationData>>(baseQuery.getPage(), baseQuery.getPageSize()),wapper );
        List<InpatientOperationData> inpatientOperationData = inpatientOperationDataMapper.selectList(null);


        return null;
    }


}
